/* ------------------------------------------------------------------- C++ OBJECT LIBRARY SOURCE CODE: string Tom Annau ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- Include files ------------------------------------------------------------------- */ #include "string.hh" #include #include #include /* ------------------------------------------------------------------- Constant definitions ------------------------------------------------------------------- */ const int FIRST_BLOCK_SIZE = 32; const int BLOCK_SIZE = 256; const int BLOCK_OFFSET = BLOCK_SIZE - FIRST_BLOCK_SIZE; /* ------------------------------------------------------------------- Constructors Assignment operators ------------------------------------------------------------------- */ string& string::operator = (const char *c) { set_length(strlen(c)); strcpy(character, c); return *this; } string& string::operator = (const string& s) { set_length(s.length); strcpy(character, s.character); return *this; } string& string::operator = (char c) { set_length(1); *character = c; return *this; } string::string(int i) { blocks_allocated = 0; set_length(0); sprintf(character, "%d", i); length = strlen(character); } string::string(double d, const char *format) { blocks_allocated = 0; set_length(0); sprintf(character, format, d); length = strlen(character); } string::~string(void) { delete [] character; } /* ------------------------------------------------------------------- Concatenations ------------------------------------------------------------------- */ string& string::operator += (char c) { set_length(length + 1); *(character + length - 1) = c; return *this; } string& string::operator += (const char *c) { int slen = length; int clen = strlen(c); set_length(length + clen); memcpy(character + slen, c, clen * sizeof(char)); return *this; } /* ------------------------------------------------------------------- Whole string operations ------------------------------------------------------------------- */ inline int white_space(char c) { return (c == SPACE || c == TAB || c == CR); } int string::blank(void) const { int i = 0; while (i < length && white_space(*(character + i))) i++; return i == length; } void string::drop_first_char(int n) { if (n > 0) { if (length > n) { bcopy(character + n, character, (length - n) * sizeof(char)); length -= n; character[length] = EOS; } else clear(); } } void string::drop_last_char(int n) { if (n > 0) { if (length >= n) { character[length - n] = EOS; length -= n; } else clear(); } } void string::lowerfy(void) { const int lowerfier = 'a' - 'A'; char *i = character, *end = character + length; for (; i < end; i++) if ((*i >= 'A') && (*i <= 'Z')) *i += lowerfier; } void string::upperfy(void) { const int upperfier = 'A' - 'a'; char *i = character, *end = character + length; for (; i < end; i++) if ((*i >= 'a') && (*i <= 'z')) *i += upperfier; } void string::strip_spaces(void) { if (length == 0) return; int left = 0, right = length - 1; while (left < length && white_space(character[left])) left++; while (right > left && white_space(character[right])) right--; operator =(middle(left, right)); } void string::remove(const string& s, int occurrence) { register int i, j; int l = strlen(s), stop = length - l, nfound = 0; l *= sizeof(char); if (l == 0 || stop < 0) return; for (i = 0; i <= stop; i++) if (memcmp(character + i, s, l) == 0) { nfound++; if (nfound == occurrence) operator =(without(i, i + l - 1)); } } void string::substitute(const string& search_string, const string& replacement) { string s; if (length == 0) return; int pos, first_pos = 0, ssl = strlen(search_string); int occurrence = 1; while ((pos = position(search_string, occurrence)) != NOT_FOUND) { if (pos && first_pos != pos) s += middle(first_pos, pos - 1); s += replacement; occurrence++; first_pos = pos + ssl; } if (first_pos < length) s += middle(first_pos); operator =(s); } /* ------------------------------------------------------------------- Substring operations ------------------------------------------------------------------- */ string string::middle(int first_pos, int second_pos) const return new_string; { register int left = first_pos, i; int right = second_pos; if (second_pos == NOT_FOUND) right = length - 1; if (left > right || left < 0 || right >= length) { cerr << "ERROR: In string::middle(), indexing error\n"; return; } new_string.set_length(right - left + 1); memcpy(new_string.character, character + left, new_string.length * sizeof(char)); } int string::frequency(const string& s) const { register int i; int l = strlen(s), stop = length - l, nfound = 0; l *= sizeof(char); if (l == 0 || stop < 0) return 0; for (i = 0; i <= stop; i++) if (memcmp(character + i, s, l) == 0) nfound++; return nfound; } int string::position(const string& s, int occurrence) const { register int i, j; int l = strlen(s), stop = length - l, nfound = 0; l *= sizeof(char); if (l == 0 || stop < 0) return NOT_FOUND; for (i = 0; i <= stop; i++) if (memcmp(character + i, s, l) == 0) { nfound++; if (nfound == occurrence) return i; } return NOT_FOUND; } /* ------------------------------------------------------------------- Field operations ------------------------------------------------------------------- */ string string::field(int field_number, int starting_pos) const return r; { if (length == 0) return; int left, right; field_boundaries(field_number, left, right, starting_pos); if (left != NOT_FOUND) r = middle(left, right); } void string::field_boundaries(int field_number, int& start, int& end, int starting_pos) const { start = end = NOT_FOUND; int left = starting_pos, current_field = 0; register int right = left; while (current_field <= field_number && right < length) { if (character[left] == QUOTES) { left++; right++; while (right < length && *(character + right) != QUOTES) right++; if (right < length) right++; } else while (right < length && !white_space(*(character + right))) right++; if (field_number == current_field) { if (right == 0) return; start = left; end = right - 1; if (character[end] == QUOTES) end--; return; } while (right < length && white_space(*(character + right))) right++; left = right; current_field++; } } int string::fields(void) const { return field_of_position(length); } int string::field_of_position(int position) const { int n_of_fields = 0, i = 0; while (i < position) { n_of_fields++; if (*(character + i) == QUOTES) { i++; while (i < position && *(character + i) != QUOTES) i++; if (i < position) i++; } else while (i < position && !white_space(*(character + i))) i++; if (i == position) return n_of_fields; while (white_space(*(character + i)) && i < position) i++; } return n_of_fields; } string string::encapsulate(void) const return s; { register int i = 0; while (i < length) if (white_space(*(character + i++))) { s = QUOTES; s += *this; s += QUOTES; for (i = 1; i < length - 1; i++) if (*(character + i) == QUOTES) *(character + i) = '\''; break; } if (i == length) s = *this; } /* ------------------------------------------------------------------- Private and protected methods ------------------------------------------------------------------- */ void string::set_length(int new_length) { int blocks_required = (new_length + BLOCK_OFFSET) / BLOCK_SIZE + 1; if (blocks_required > blocks_allocated) { char *new_space = new char[blocks_required * BLOCK_SIZE - BLOCK_OFFSET]; if (blocks_allocated > 0) { strcpy(new_space, character); delete [] character; } character = new_space; blocks_allocated = blocks_required; } length = new_length; *(character + length) = EOS; } /* ------------------------------------------------------------------- Stream functions ------------------------------------------------------------------- */ istream& operator >> (istream& in, string& s) { s.clear(); char c; in.get(c); int in_quotes = 0; while ((in_quotes || c != CR) && !in.eof()) { s += c; if (c == QUOTES) in_quotes = !in_quotes; in.get(c); } return in; } ostream& operator < (ostream& out, const string& s) { out < s.length; out.write(s.character, s.length * sizeof(char)); return out; } istream& operator > (istream& in, string& s) { int l; in > l; s.set_length(l); in.read(s.character, l * sizeof(char)); return in; }